
// Generic data container.
DataStore = {
    // init method:
    // expects input data returned from raw SQL commands of in json format:
    //  @param data = {
    //      meta: [[<colname>, ...], ...],      // The column names are an array of arrays' 0th entries.
    //      result: [[<row_col0>, ...], ...]    // The rows are returned in the same order as the columns above.
    //  }
    init: function (data) {
        this.filters = {};
        this.meta = data.meta;
        this.set_indices(data.meta);
        this.load_data(data.result);
        this.set_default_filters();
        return this;
    },
    
    set_default_filters: function() {
        var idx, idx_num, tmpv, v;
        
        for (idx_num in this.indices) {
            idx = this.indices[idx_num];
            if (idx.name !== 'year_index' && idx.name !== 'spatial_index') {
                this.filters[idx.name] = CE.UTIL.get_one_key(idx.values);
            }
            
            // sort the value lists.
            tmpv = idx.values;
            idx.values = [];
            for (v in tmpv) {
                idx.values.push(v);
            }
            idx.values.sort();
        }
    },
    
    // populates the data store with raw db output (JSON) from python's sql hooks.
    load_data: function (result) {
        var k, prev_node, data_node, idx, idx_num, node_key;
        this.records = {};
        for (k in result) {
            data_node = this.records;
            for (idx_num in this.indices) {
                idx = this.indices[idx_num];
                prev_node = data_node;
                node_key = '' + result[k][idx.data_pos];
                if (!data_node[node_key]) {
                    data_node[node_key] = {};
                }
                data_node = data_node[node_key];
                if (idx.values[node_key]) {
                    idx.values[node_key]++;
                } else {
                    idx.values[node_key] = 0;
                }
            }
            prev_node[node_key] = result[k];
        }
    },
    
    // The indices are a sequence of db columns used to efficiently filter the records by attributes.
    // Their "values" attribute contains all possible values for that index.
    set_indices: function (meta) {
        var k, index;
        this.indices = [];
        this.indices_by_name = {};
        for (k in meta) {
            if (/_index$/.test(meta[k][0])) {
                index = {
                    name: meta[k][0],
                    values: {},
                    data_pos: k
                };
                this.indices.push(index);
                this.indices_by_name[index.name] = index;
            }
        }
    },
    
    // Fetch a record based on a set of filters.
    fetch: function (filters) {
        var idx_num, node_key, idx, data_node = this.records;
        for (idx_num in this.indices) {
            //console.log (filters[this.indices[idx_num].name] || this.filters[this.indices[idx_num].name]);
            node_key = filters[this.indices[idx_num].name] || this.filters[this.indices[idx_num].name];
            data_node = data_node[node_key];
            if (!data_node) {
                return null;
            }
        }
        return data_node;
    },
    // Fetch a record based on a set of filters.
    fetch_formatted: function (filters) {
        var k, data_node = this.fetch(filters),
            data_obj = {};
        if (data_node) for (k in this.meta) {
            data_obj[this.meta[k][0]] = data_node[k];
        }
        return data_obj;
    }
};
